home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------------
- // File: Validate.h
- //
- // Desc: DirectShow sample code - parameter validation macros.
- //
- // Copyright (c) 1997-2001 Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
-
-
- // Summary:
- //
- // V_INAME(interfacename) - Set the interface name for error display
- // V_STRUCTPTR_READ(ptr,type) - A dwSize struct which we will read
- // V_STRUCTPTR_WRITE(ptr,type) - A dwSize struct which we will read/write
- // V_PTR_READ(ptr,type) - A typed ptr w/o a dwSize which we will read
- // V_PTR_WRITE(ptr,type) - A typed ptr w/o a dwSize which we will read/write
- // V_PTR_WRITE_OPT(ptr,type) - An optional typed ptr w/o a dwSize which we will read/write
- // V_BUFPTR_READ(ptr,size) - A variable-size buffer that we will read
- // V_BUFPTR_READ_OPT(ptr,size) - An optional variable-size buffer that we will read
- // V_BUFPTR_WRITE(ptr,size) - A variable-size buffer that we will read/write
- // V_BUFPTR_WRITE_OPT(ptr,size) - An optional variable-size buffer that we will read/write
- // V_PTRPTR_WRITE(ptrptr) - A pointer to a pointer to write to
- // V_PTRPTR_WRITE_OPT(ptrptr) - A pointer to a pointer to write to that is optional
- // V_PUNKOUTER(punk) - A pointer to a controlling unknown, aggregation supported
- // V_PUNKOUTER_NOADD(punk) - A pointer to a controlling unknown, aggregation not supported
- // V_INTERFACE(ptr) - A pointer to a COM interface
- // V_INTERFACE_OPT(ptr) - An optional pointer to a COM interface
- // V_REFGUID(ref) - A reference to a GUID (type REFGUID)
- // V_HWND(hwnd) - A window handle
- // V_HWNDOPT(hwnd) - An optional window handle
- //
- // For handling different versions of structures:
- //
- // V_STRUCTPTR_READ_VER(ptr,ver) - Begin a struct version block for read access
- // At the end, 'ver' will contain the
- // discovered version of the struct
- // V_STRUCTPTR_READ_VER_CASE(base,ver) - Test struct against version ver of
- // type 'base'.
- // V_STRUCTPTR_READ_VER_END(base,ptr) - End a struct version block
- //
- // V_STRUCTPTR_WRITE_VER(ptr,ver) - Struct version block for write access
- // V_STRUCTPTR_WRITE_VER_CASE(base,ver)
- // V_STRUCTPTR_WRITE_VER_END(base,ptr)
- //
- // The struct version block expects type names of a base type followed by a
- // numeric version, such as
- //
- // typedef struct { } FOO7;
- // typedef struct { } FOO8;
- //
- // In the header FOO and LPFOO are conditionally typedef'd based on a version
- // #define. The DLL will be compiled with the latest version number and hence
- // the largest version of the struct.
- //
- // Since Windows headers are compiled by default with 8-byte alignment, adding
- // one DWORD may not cause the size of the structure to change. If this happens
- // you will get a 'case label already used' error on one of the VER_CASE macros.
- // If this happens, you can get around it by adding a dwReserved field to the
- // end of the struct to force the padding.
- //
- // 'optional' means the pointer is allowed to be NULL by the interface specification.
- //
- // Sample usage:
- //
- // int IDirectMusic::SetFooBarInterface(
- // LPDMUS_REQUESTED_CAPS pCaps, // Caps w/ dwSize (read-only)
- // LPVOID pBuffer, // Buffer we will fill in
- // DWORD cbSize, // Size of the buffer
- // PDIRECTMUSICBAR pBar) // Callback interface for bar on this buffer
- // {
- // V_INTERFACE(IDirectMusic::SetFooBarInterface);
- // V_BUFPTR_WRITE(pBuffer, cbSize);
- // V_INTERFACE(pBar);
- // DWORD dwCapsVer; // Must be a DWORD!!!
- //
- // V_STRUCTPTR_READ_VER(pCaps, dwCapsVer);
- // V_STRUCTPTR_READ_VER_CASE(DMUS_REQUESTED_CAPS, 7);
- // V_STRUCTPTR_READ_VER_CASE(DMUS_REQUESTED_CAPS, 8);
- // V_STRUCTPTR_READ_VER_END_(DMUS_REQUESTED_CAPS, pCaps);
- //
- // // At this point, if we are still in the function we have a valid pCaps
- // // pointer and dwCapsVer is either 7 or 8, indicating the version of
- // // the struct passed in.
- //
- // ...
- // }
- //
- #ifndef _VALIDATE_H_
- #define _VALIDATE_H_
-
-
- #ifdef DBG
- #include <stddef.h>
-
- #include "debug.h"
-
- // To turn on DebugBreak on parameter error, use the following or -DRIP_BREAK in the build:
- //
- //#define RIP_BREAK 1
-
- #ifdef RIP_BREAK
- #define _RIP_BREAK DebugBreak();
- #else
- #define _RIP_BREAK
- #endif
-
- #define V_INAME(x) \
- static const char __szValidateInterfaceName[] = #x;
-
- #define RIP_E_POINTER(ptr) \
- { Trace(-1, "%s: Invalid pointer " #ptr "\n", __szValidateInterfaceName); \
- _RIP_BREAK \
- return E_POINTER; }
-
- #define RIP_E_INVALIDARG(ptr) \
- { Trace(-1, "%s: Invalid argument " #ptr "\n", __szValidateInterfaceName); \
- _RIP_BREAK \
- return E_INVALIDARG; }
-
- #define RIP_E_HANDLE(h) \
- { Trace(-1, "%s: Invalid handle " #h "\n", __szValidateInterfaceName); \
- _RIP_BREAK \
- return E_HANDLE; }
-
- #define RIP_W_INVALIDSIZE(ptr) \
- { Trace(-1, "%s: " #ptr "->dwSize matches no known structure size. Defaulting to oldest structure.\n", \
- __szValidateInterfaceName); \
- _RIP_BREAK \
- }
-
- #define RIP_E_INVALIDSIZE(ptr) \
- { Trace(-1, "%s: " #ptr "->dwSize is too small\n", __szValidateInterfaceName); \
- _RIP_BREAK \
- return E_INVALIDARG; }
-
- #define RIP_E_BLOCKVSDWSIZE(ptr) \
- { Trace(-1, "%s: " #ptr " does not point to as much memory as " #ptr "->dwSize indicates\n", \
- __szValidateInterfaceName); \
- _RIP_BREAK \
- return E_INVALIDARG; }
-
- // NOTE: The DebugBreak() not in #ifdef is intentional - this is something that
- // must be fixed in our code, not an app-generated error.
- //
- #define V_ASSERT(exp) \
- { if (!(exp)) { \
- Trace(-1, "%s@%s: %s\n", __FILE__, __LINE__, #exp); \
- DebugBreak(); }}
-
- #else
-
- #define V_INAME(x)
- #define RIP_E_POINTER(ptr) { return E_POINTER; }
- #define RIP_E_INVALIDARG(ptr) { return E_INVALIDARG; }
- #define RIP_E_HANDLE(h) { return E_HANDLE; }
- #define RIP_E_BLOCKVSDWSIZE(ptr) { return E_INVALIDARG; }
- #define RIP_W_INVALIDSIZE(ptr)
- #define RIP_E_INVALIDSIZE(ptr) { return E_INVALIDARG; }
- #define V_ASSERT(exp)
-
- #endif // DBG
-
- // A passed struct we will only read from or may write to. Must be a struct
- // with a dwSize.
- //
- // int foo(CFoo *pFoo)
- // ...
- // V_STRUCTPTR_READ(pFoo, CFoo);
- // V_STRUCTPTR_WRITE(pFoo, CFoo);
- //
- // Use _PTR_ variants for structs w/o a dwSize
- //
- #define V_STRUCTPTR_READ(ptr,type) \
- { V_ASSERT(offsetof(type, dwSize) == 0); \
- if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
- if (ptr->dwSize < sizeof(type)) RIP_E_INVALIDSIZE(ptr); \
- if (IsBadReadPtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); }
-
- #define V_STRUCTPTR_WRITE(ptr,type) \
- { V_ASSERT(offsetof(type, dwSize) == 0); \
- if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
- if (ptr->dwSize < sizeof(type)) RIP_E_INVALIDSIZE(ptr); \
- if (IsBadWritePtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); }
-
- #define V_PTR_READ(ptr,type) \
- { if (IsBadReadPtr(ptr, sizeof(type))) RIP_E_POINTER(ptr); }
-
- #define V_PTR_WRITE(ptr,type) \
- { if (IsBadWritePtr(ptr, sizeof(type))) RIP_E_POINTER(ptr); }
-
- #define V_PTR_WRITE_OPT(ptr,type) \
- { if (ptr) if (IsBadWritePtr(ptr, sizeof(type))) RIP_E_POINTER(ptr); }
-
- // A buffer pointer with separate length (not defined by the pointer type) we will only
- // read from or may write to.
- //
- // int foo(LPVOID *pBuffer, DWORD cbBuffer)
- // ...
- // V_BUFPTR_READ(pBuffer, cbBuffer);
- // V_BUFPTR_WRITE(pBuffer, cbBuffer);
- //
- #define V_BUFPTR_READ(ptr,len) \
- { if (IsBadReadPtr(ptr, len)) RIP_E_POINTER(ptr); }
-
- #define V_BUFPTR_READ_OPT(ptr,len) \
- { if (ptr) V_BUFPTR_READ(ptr,len); }
-
- #define V_BUFPTR_WRITE(ptr,len) \
- { if (IsBadWritePtr(ptr, len)) RIP_E_POINTER(ptr); }
-
- #define V_BUFPTR_WRITE_OPT(ptr,len) \
- { if (ptr) V_BUFPTR_WRITE(ptr,len); }
-
- // A pointer to a pointer (such as a pointer to an interface pointer) to return
- //
- // int foo(IReturnMe **ppRet)
- // ...
- // V_PTRPTR_WRITE(ppRet);
- // V_PTRPTR_WRITE_OPT(ppRet);
- //
- #define V_PTRPTR_WRITE(ptr) \
- { if (IsBadWritePtr(ptr, sizeof(void*))) RIP_E_POINTER(ptr); }
-
- #define V_PTRPTR_WRITE_OPT(ptr) \
- { if (ptr) if (IsBadWritePtr(ptr, sizeof(void*))) RIP_E_POINTER(ptr); }
-
- // A pointer to a controlling unknown
- //
- #define V_PUNKOUTER(punk) \
- { if (punk && IsBadCodePtr(punk)) RIP_E_POINTER(ptr); }
-
- // A pointer to a controlling unknown for which we don't support aggregation
- //
- #define V_PUNKOUTER_NOAGG(punk) \
- { if (punk && IsBadReadPtr(punk, sizeof(IUnknown))) RIP_E_POINTER(ptr); \
- if (punk) return CLASS_E_NOAGGREGATION; }
-
- // Validate an incoming interface pointer.
- //
- struct _V_GENERIC_INTERFACE
- {
- FARPROC *(__vptr[1]);
- };
-
- #define V_INTERFACE(ptr) \
- { if (IsBadReadPtr(ptr, sizeof(_V_GENERIC_INTERFACE))) RIP_E_POINTER(ptr); \
- if (IsBadReadPtr(*reinterpret_cast<_V_GENERIC_INTERFACE*>(ptr)->__vptr, sizeof(FARPROC))) \
- RIP_E_POINTER(ptr); \
- if (IsBadCodePtr(*(reinterpret_cast<_V_GENERIC_INTERFACE*>(ptr)->__vptr)[0])) RIP_E_POINTER(ptr); }
-
- #define V_INTERFACE_OPT(ptr) \
- { if (ptr) V_INTERFACE(ptr); }
-
- // Validation for a reference to a GUID, which we only ever read.
- //
- #define V_REFGUID(ref) \
- { if (IsBadReadPtr((void*)&ref, sizeof(GUID))) RIP_E_POINTER((void*)&ref); }
-
- // Validation for a window handle
- //
- #define V_HWND(h) \
- { if (!IsWindow(h)) RIP_E_HANDLE(h); }
-
- #define V_HWND_OPT(h) \
- { if (h) if (!IsWindow(h)) RIP_E_HANDLE(h); }
-
- // Validation for multiple sized structs based on version
- //
- #define V_STRUCTPTR_READ_VER(ptr,ver) \
- { ver = 7; DWORD *pdw = &ver; \
- if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
- if (IsBadReadPtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); \
- switch ((ptr)->dwSize) {
-
- #define V_STRUCTPTR_READ_VER_CASE(basetype,ver) \
- case sizeof(basetype##ver) : \
- V_ASSERT(offsetof(basetype##ver, dwSize) == 0); \
- *pdw = ver; break;
-
- #define V_STRUCTPTR_READ_VER_END(basetype,ptr) \
- default : if ((ptr)->dwSize > sizeof(basetype##7)) \
- { RIP_W_INVALIDSIZE(ptr); } else \
- RIP_E_INVALIDSIZE(ptr); }}
-
-
- #define V_STRUCTPTR_WRITE_VER(ptr,ver) \
- { ver = 7; DWORD *pdw = &ver; \
- if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
- if (IsBadWritePtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); \
- switch ((ptr)->dwSize) {
-
- #define V_STRUCTPTR_WRITE_VER_CASE(basetype,ver) \
- case sizeof(basetype##ver) : \
- V_ASSERT(offsetof(basetype##ver, dwSize) == 0); \
- *pdw = ver; break;
-
- #define V_STRUCTPTR_WRITE_VER_END(basetype,ptr) \
- default : if ((ptr)->dwSize > sizeof(basetype##7)) \
- { RIP_W_INVALIDSIZE(ptr); } else \
- RIP_E_INVALIDSIZE(ptr); }}
-
-
-
- #endif // _VALIDATE_H_
-